// PictureButton.cpp : implementation file
//

#include "stdafx.h"
#include "PictureButton.h"


// CPictureButton
CPictureButton::CPictureButton(): m_bOver(FALSE), m_bTracking(FALSE), m_bSelected(FALSE), m_bFocus(FALSE), m_bNormal(TRUE)
{
	m_bPressed = FALSE;
	m_hLinkCursor = NULL;

	m_pMemHoDC = m_pMemDeDC = m_pMemPrDC = m_pMemDiDC = m_pMemDestDC = NULL;
	m_pMemHoBitmap = m_pMemDeBitmap = m_pMemPrBitmap = m_pMemDiBitmap = m_pMemDestBitmap = NULL;

	m_nStringFormat.SetAlignment(StringAlignmentCenter);
	m_nStringFormat.SetLineAlignment(StringAlignmentCenter);
}

CPictureButton::~CPictureButton()
{
	if(m_pMemHoDC) { 
		CBitmap* pOldBmp = m_pMemHoDC->SelectObject((CBitmap*)0);
		DeleteDC(m_pMemHoDC->GetSafeHdc());
		delete m_pMemHoDC;  m_pMemHoDC = NULL;
	}
	if(m_pMemHoBitmap) { delete m_pMemHoBitmap;  m_pMemHoBitmap = NULL; }

	if(m_pMemDeDC) { 
		CBitmap* pOldBmp = m_pMemDeDC->SelectObject((CBitmap*)0);
		DeleteDC(m_pMemDeDC->GetSafeHdc());
		delete m_pMemDeDC;  m_pMemDeDC = NULL;
	}
	if(m_pMemDeBitmap) { delete m_pMemDeBitmap;  m_pMemDeBitmap = NULL; }

	if(m_pMemPrDC) { 
		CBitmap* pOldBmp = m_pMemPrDC->SelectObject((CBitmap*)0);
		DeleteDC(m_pMemPrDC->GetSafeHdc());
		delete m_pMemPrDC;  m_pMemPrDC = NULL;
	}
	if(m_pMemPrBitmap) { delete m_pMemPrBitmap;  m_pMemPrBitmap = NULL; }

	if(m_pMemDiDC) { 
		CBitmap* pOldBmp = m_pMemDiDC->SelectObject((CBitmap*)0);
		DeleteDC(m_pMemDiDC->GetSafeHdc());
		delete m_pMemDiDC;  m_pMemDiDC = NULL;
	}
	if(m_pMemDiBitmap) { delete m_pMemDiBitmap;  m_pMemDiBitmap = NULL; }

	if(m_pMemDestDC) {
		CBitmap* pOldBmp = (CBitmap*)m_pMemDestDC->SelectObject((CBitmap*)0);
		DeleteDC(m_pMemDestDC->GetSafeHdc());  delete m_pMemDestDC;  m_pMemDestDC = NULL;
	}
	if(m_pMemDestBitmap) { delete m_pMemDestBitmap;  m_pMemDestBitmap = NULL; }
}

BOOL CPictureButton::SetBntPicsID(UINT nHo,UINT nDe,UINT nPr,UINT nDi)
{
	m_nPicHoId = nHo;
	m_nPicDeId = nDe;
	m_nPicPrId = nPr;
	m_nPicDiId = nDi;
	return TRUE;
}

void CPictureButton::SetHandCursor()
{
	if(m_hLinkCursor == NULL)                // No cursor handle - load our own
		m_hLinkCursor=::LoadCursor(NULL, IDC_HAND);
}

BEGIN_MESSAGE_MAP(CPictureButton, CButton)
	ON_WM_MOUSEMOVE()
	ON_WM_ERASEBKGND()
	ON_WM_SETCURSOR()
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
	ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
END_MESSAGE_MAP()

// CPictureButton message handlers

void CPictureButton::PreSubclassWindow()
{
	ModifyStyle(0, BS_OWNERDRAW);
	CButton::PreSubclassWindow();
}

BOOL CPictureButton::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

BOOL CPictureButton::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/) 
{
	if(m_hLinkCursor) {
		::SetCursor(m_hLinkCursor);
		return TRUE;
	}
	return FALSE;
}

void CPictureButton::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	if(!m_bTracking) {
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = m_hWnd;
		tme.dwFlags = TME_LEAVE | TME_HOVER;
		tme.dwHoverTime = 1;
		//m_bTracking = _TrackMouseEvent(&tme);
		m_bTracking = TrackMouseEvent(&tme);
	}

	CButton::OnMouseMove(nFlags, point);
}

LRESULT CPictureButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
	m_bOver = FALSE;         
	m_bTracking = FALSE;        
	if(!m_bPressed)
		InvalidateRect(NULL, FALSE);  
	
	return 0;
}

LRESULT CPictureButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
	m_bOver = TRUE;  
	InvalidateRect(NULL); 
	return 0;
}

void CPictureButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    m_nState = lpDrawItemStruct->itemState;
	CDC* dc = CDC::FromHandle(lpDrawItemStruct->hDC);

    DrawBackground();
	DrawControl();
	dc->BitBlt(0, 0, m_rectWindow.Width(), m_rectWindow.Height(), m_pMemDestDC, 0, 0, SRCCOPY);
	DrawString(*dc);
}

void CPictureButton::DrawBackground()
{
	if(NULL == m_pMemBgDC) {
		CDialogExt* wndDlgex = (CDialogExt*)GetParent();
		m_pMemBgDC = wndDlgex->GetDialogCdc();

		GetWindowRect(m_rectWindow);  wndDlgex->ScreenToClient(&m_rectWindow);
	}
}

void CPictureButton::DrawControl()
{
	if(NULL == m_pMemBgDC) return;

	if(NULL == m_pMemHoDC) LoadPicsToMemDC(m_pMemHoDC, m_pMemHoBitmap, m_nPicHoId);
	if(NULL == m_pMemDeDC) LoadPicsToMemDC(m_pMemDeDC, m_pMemDeBitmap, m_nPicDeId);
	if(NULL == m_pMemPrDC) LoadPicsToMemDC(m_pMemPrDC, m_pMemPrBitmap, m_nPicPrId);
	if(NULL == m_pMemDiDC) LoadPicsToMemDC(m_pMemDiDC, m_pMemDiBitmap, m_nPicDiId);

	if(NULL == m_pMemDestDC) {
		CDC* tmpDC = GetDC();
		m_pMemDestDC = new CDC();
		m_pMemDestDC->CreateCompatibleDC(tmpDC);
		m_pMemDestBitmap = new CBitmap();
		m_pMemDestBitmap->CreateCompatibleBitmap(tmpDC, m_rectWindow.Width(), m_rectWindow.Height());
		m_pMemDestDC->SelectObject(m_pMemDestBitmap);
		ReleaseDC(tmpDC);
	}

	if(m_bOver) {		
		if(m_nState & ODS_SELECTED)
			m_pMemDestDC->BitBlt(0, 0, m_rectWindow.Width(), m_rectWindow.Height(), m_pMemPrDC, 0, 0, SRCCOPY);
		else if( m_bPressed)
			m_pMemDestDC->BitBlt(0, 0, m_rectWindow.Width(), m_rectWindow.Height(), m_pMemPrDC, 0, 0, SRCCOPY);
		else
			m_pMemDestDC->BitBlt(0, 0, m_rectWindow.Width(), m_rectWindow.Height(), m_pMemHoDC, 0, 0, SRCCOPY);		
	}
	else if(m_nState & ODS_DISABLED)
		m_pMemDestDC->BitBlt(0, 0, m_rectWindow.Width(), m_rectWindow.Height(), m_pMemDiDC, 0, 0, SRCCOPY);
	else {
		if (m_bPressed)
			m_pMemDestDC->BitBlt(0, 0, m_rectWindow.Width(), m_rectWindow.Height(), m_pMemPrDC, 0, 0, SRCCOPY);
		else
			m_pMemDestDC->BitBlt(0, 0, m_rectWindow.Width(), m_rectWindow.Height(), m_pMemDeDC, 0, 0, SRCCOPY);
	}
}

void CPictureButton::DrawString(CDC& dc)
{
	GetWindowTextW(m_strWindowText);
	if(!m_strWindowText.IsEmpty()){
		Graphics graphics(dc.GetSafeHdc());
		graphics.DrawString(m_strWindowText,
			-1,
			m_pFont,
			RectF((REAL)0,(REAL)0,(REAL)m_rectWindow.Width(),(REAL)m_rectWindow.Height()),
			&m_nStringFormat,
			m_pBrush);
	}
}

void CPictureButton::LoadPicsToMemDC(CDC* &pMemDC, CBitmap* &pMemBitmap, UINT nPicID)
{
	if(pMemDC) { delete pMemDC;  pMemDC = NULL; }
	if(pMemBitmap) { delete pMemBitmap;  pMemBitmap = NULL; }

	CDC *pDC = GetDC();
	pMemDC= new CDC();
	pMemDC->CreateCompatibleDC(pDC);

	pMemBitmap = new CBitmap();
	pMemBitmap->CreateCompatibleBitmap(pDC, m_rectWindow.Width(), m_rectWindow.Height());

	pMemDC->SelectObject(pMemBitmap);
	pMemDC->BitBlt(0, 0, m_rectWindow.Width(), m_rectWindow.Height(), m_pMemBgDC, m_rectWindow.left, m_rectWindow.top, SRCCOPY);

	Image *pBgImage;
	if(ImageFromIDResource(nPicID, _T("PNG"), pBgImage)){
		Graphics graphics(pMemDC->GetSafeHdc());
		graphics.DrawImage(pBgImage, Rect(0, 0, m_rectWindow.Width(), m_rectWindow.Height()), 0, 0, pBgImage->GetWidth(), pBgImage->GetHeight(), UnitPixel);
	}

	ReleaseDC(pDC);
}

BOOL CPictureButton::ImageFromIDResource(UINT nID, LPCTSTR sTR, Image* &pImg)
{
	HINSTANCE hInst = AfxGetResourceHandle();
	HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type
	if(!hRsrc) return FALSE;

	// load resource into memory
	DWORD len = SizeofResource(hInst, hRsrc);
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
	if(!lpRsrc) return FALSE;

	// Allocate global memory on which to create stream
	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
	memcpy(pmem,lpRsrc,len);
	IStream* pstm;
	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
	// load from stream
	pImg=Gdiplus::Image::FromStream(pstm);
	// free/release stuff
	GlobalUnlock(m_hMem);
	pstm->Release();
	FreeResource(lpRsrc);
	return TRUE;
}